//// http://www.monografias.com/trabajos20/cifrado-en-bloques/cifrado-en-bloques2.shtml
//// http://orlingrabbe.com/des.htm
//// http://www.arielorellana.net/des.htm
//// http://en.wikipedia.org/wiki/DES_supplementary_material
//// http://daniel-albuschat.blogspot.com/2009/06/compile-time-array-in-c-using-templates.html
//// http://stackoverflow.com/questions/2978259/programmatically-create-static-arrays-at-compile-time-in-c
//// http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c
//
//// Javascript tester: 
//	// http://people.eku.edu/styere/Encrypt/JS-DES.html
//
//// TODO: ver std::bitset
//	// http://new.cplusplus.com/reference/stl/bitset/
//
//// TODO: ver Boost dynamic_bitset
//	// http://www.boost.org/doc/libs/1_36_0/libs/dynamic_bitset/dynamic_bitset.html#acknowledgements
//
//
//
//#include <algorithm>
//#include <iostream>
//#include <iterator>
////#include <boost/assert.hpp>
////#include <boost/static_assert.hpp>
//#include <boost/archive/iterators/transform_width.hpp>
//
//#include "permutator.hpp"
//#include "des_tables.hpp"
//#include "bit_array.hpp"
//
////using static_array::e;
//
//
//void des_encrypt()
//{}
//
//const unsigned char key[] = { 0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e };				//http://people.eku.edu/styere/Encrypt/JS-DES.html
////const unsigned char key[] = { 0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1 };
//
//unsigned char cd0[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd1[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd2[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd3[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd4[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd5[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd6[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd7[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd8[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd9[]  = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd10[] = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd11[] = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd12[] = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd13[] = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd14[] = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd15[] = { 0, 0, 0, 0, 0, 0, 0 };
//unsigned char cd16[] = { 0, 0, 0, 0, 0, 0, 0 };
//
//unsigned char k1[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k2[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k3[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k4[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k5[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k6[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k7[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k8[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k9[]  = { 0, 0, 0, 0, 0, 0 };
//unsigned char k10[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char k11[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char k12[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char k13[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char k14[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char k15[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char k16[] = { 0, 0, 0, 0, 0, 0 };
//
//
//const unsigned char message[] = { 'F', 'E', 'R', 'N', 'A', 'N', 'D', 'O' };
////const unsigned char message[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
//
//
//unsigned char ip_left[] =  { 0, 0, 0, 0 };
//unsigned char ip_right[] = { 0, 0, 0, 0 };
//unsigned char ip_right_expanded[] = { 0, 0, 0, 0, 0, 0 };
//unsigned char ip_right_expanded_xor[] = { 0, 0, 0, 0, 0, 0 };
////unsigned char temp_32_bits[] = { 0, 0, 0, 0 };
////unsigned char left[] = { 0, 0, 0, 0 };
////unsigned char right[] = { 0, 0, 0, 0 };
//
//unsigned char final[] = { 0, 0, 0, 0 };
//
////TODO: parametrizar esta funcion par en vez de solo aplicar XOR aplicar un Predicado parametrizable...
//template <
//	typename ElemType
//	, size_t Size
//>
//struct xor_array_impl
//{
//	//typedef typename PermutationTable::value_type index_type;
//
//	//template < index_type Index >
//	template < int Index >
//	static void xor( const ElemType (&left_array)[Size],  const ElemType (&right_array)[Size], ElemType (&target_array)[Size] )
//	{
//		xor_impl<Index>( left_array, right_array, target_array );
//		xor<Index-1>( left_array, right_array, target_array );
//	}
//
//	template <>
//	static void xor<0>( const ElemType (&left_array)[Size], const ElemType (&right_array)[Size], ElemType (&target_array)[Size] )
//	{
//		xor_impl<0>( left_array, right_array, target_array );
//	}
//
//private:
//
//	//template < index_type Index >
//	template < int Index >
//	static void xor_impl( const ElemType (&left_array)[Size], const ElemType (&right_array)[Size], ElemType (&target_array)[Size] )
//	{
//		//TODO: parametrizar el XOR como un predicado ... una MetaFuncion... 
//		target_array[Index] = left_array[Index] ^ right_array[Index];
//	}
//};
//
//
//template <typename ElemType, size_t Size>
//void xor_array( const ElemType (&left_array)[Size], const ElemType (&right_array)[Size], ElemType (&target_array)[Size] )
//{
//	xor_array_impl<ElemType, Size>::xor<Size-1>(left_array, right_array, target_array);
//}
//
//
//
//
////Generation of sub-keys
//void step0()
//{
//	//typedef permutator<rotate_table_1, bit_adjuster::big_endian_des_tables, bit_adjuster::big_endian> perm_rot_1;
//	//typedef permutator<rotate_table_2, bit_adjuster::big_endian_des_tables, bit_adjuster::big_endian> perm_rot_2;
//	//typedef permutator<pc2_table, bit_adjuster::big_endian_des_tables, bit_adjuster::big_endian> perm_pc2;
//	//permutator<pc1_table, bit_adjuster::big_endian_des_tables, bit_adjuster::big_endian>::call(key, cd0);
//
//	typedef permutator_des<rotate_table_1> perm_rot_1;
//	typedef permutator_des<rotate_table_2> perm_rot_2;
//	typedef permutator_des<pc2_table> perm_pc2;
//	permutator_des<pc1_table>::call(key, cd0);
//
//
//	//TODO: elegir tabla de rotacion 1 o 2 dependiendo de la rotation_table. Usar enable_if si es necesario...
//
//	perm_rot_1::call(cd0,  cd1);
//	perm_rot_1::call(cd1,  cd2);
//	
//	perm_rot_2::call(cd2,  cd3);
//	perm_rot_2::call(cd3,  cd4);
//	perm_rot_2::call(cd4,  cd5);
//	perm_rot_2::call(cd5,  cd6);
//	perm_rot_2::call(cd6,  cd7);
//	perm_rot_2::call(cd7,  cd8);
//	
//	perm_rot_1::call(cd8,  cd9);
//
//	perm_rot_2::call(cd9,  cd10);
//	perm_rot_2::call(cd10, cd11);
//	perm_rot_2::call(cd11, cd12);
//	perm_rot_2::call(cd12, cd13);
//	perm_rot_2::call(cd13, cd14);
//	perm_rot_2::call(cd14, cd15);
//
//	perm_rot_1::call(cd15, cd16);
//
//
//	perm_pc2::call(cd1,  k1);
//	perm_pc2::call(cd2,  k2);
//	perm_pc2::call(cd3,  k3);
//	perm_pc2::call(cd4,  k4);
//	perm_pc2::call(cd5,  k5);
//	perm_pc2::call(cd6,  k6);
//	perm_pc2::call(cd7,  k7);
//	perm_pc2::call(cd8,  k8);
//	perm_pc2::call(cd9,  k9);
//	perm_pc2::call(cd10, k10);
//	perm_pc2::call(cd11, k11);
//	perm_pc2::call(cd12, k12);
//	perm_pc2::call(cd13, k13);
//	perm_pc2::call(cd14, k14);
//	perm_pc2::call(cd15, k15);
//	perm_pc2::call(cd16, k16);
//	
//
//
//
//	//bit_print(key);  std::cout << std::endl;
//	//bit_print(cd0);  std::cout << std::endl;
//	//bit_print(cd1);  std::cout << std::endl;
//	//bit_print(cd2);  std::cout << std::endl;
//	//bit_print(cd3);  std::cout << std::endl;
//	//bit_print(cd4);  std::cout << std::endl;
//	//bit_print(cd5);  std::cout << std::endl;
//	//bit_print(cd6);  std::cout << std::endl;
//	//bit_print(cd7);  std::cout << std::endl;
//	//bit_print(cd8);  std::cout << std::endl;
//	//bit_print(cd9);  std::cout << std::endl;
//	//bit_print(cd10); std::cout << std::endl;
//	//bit_print(cd11); std::cout << std::endl;
//	//bit_print(cd12); std::cout << std::endl;
//	//bit_print(cd13); std::cout << std::endl;
//	//bit_print(cd14); std::cout << std::endl;
//	//bit_print(cd15); std::cout << std::endl;
//	//bit_print(cd16); std::cout << std::endl;
//
//	//std::cout << "------------------ keys -------------------------------" << std::endl;
//
//	//bit_print(k1);  std::cout << std::endl;
//	//bit_print(k2);  std::cout << std::endl;
//	//bit_print(k3);  std::cout << std::endl;
//	//bit_print(k4);  std::cout << std::endl;
//	//bit_print(k5);  std::cout << std::endl;
//	//bit_print(k6);  std::cout << std::endl;
//	//bit_print(k7);  std::cout << std::endl;
//	//bit_print(k8);  std::cout << std::endl;
//	//bit_print(k9);  std::cout << std::endl;
//	//bit_print(k10); std::cout << std::endl;
//	//bit_print(k11); std::cout << std::endl;
//	//bit_print(k12); std::cout << std::endl;
//	//bit_print(k13); std::cout << std::endl;
//	//bit_print(k14); std::cout << std::endl;
//	//bit_print(k15); std::cout << std::endl;
//	//bit_print(k16); std::cout << std::endl;
//	
//}
//
//
//
//unsigned char s( unsigned char table_index, unsigned char b )
//{
//	unsigned char row = 0;
//	unsigned char column = 0;
//
//	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(b, row);
//	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(b, column);
//
//	unsigned int s_index = (row * 16) + column;
//
//	//std::cout << " b: ";
//	//bit_print(b, 6);
//	//std::cout << " row: " << (unsigned int)row << " col: " << (unsigned int)column << " val: " << (unsigned int)s_tables[table_index][s_index];
//	//std::cout << " bin: ";
//	//bit_print(s_tables[table_index][s_index]);
//	//std::cout << " sindex: " << (unsigned int)s_index << std::endl;
//
//
//	return s_tables[table_index][s_index];
//}
//
//template <int N>
//struct for_loop 
//{
//    enum { value = N * for_loop<N - 1>::value };
//};
// 
//template <>
//struct for_loop<0>
//{
//    enum { value = 1 };
//};
//
//
//// Fractioning of the text into 64-bit (8 octet) blocks;
//void step1()
//{
//	permutator_des<ip_table_left>::call(message, ip_left);
//	permutator_des<ip_table_right>::call(message, ip_right);
//	permutator_des<e_table>::call(ip_right, ip_right_expanded);
//	xor_array(ip_right_expanded, k1, ip_right_expanded_xor);
//
//	std::cout << "left:       "; bit_print(ip_left); std::cout << std::endl;
//	std::cout << "right:      "; bit_print(ip_right); std::cout << std::endl;
//	std::cout << "key 1:      "; bit_print(k1); std::cout << std::endl;
//	std::cout << "ip ex:      "; bit_print(ip_right_expanded); std::cout << std::endl;
//	std::cout << "ip ex xor:  "; bit_print(ip_right_expanded_xor); std::cout << std::endl;
//
//	//-----------------------------------------------------------
//	using boost::archive::iterators::transform_width;
//	
//	typedef transform_width<char*, 6, 8> base64_text;
//	
//	base64_text it( ip_right_expanded_xor );
//	base64_text end( ip_right_expanded_xor+6 );
//		
//	bit_array<4, 8> temp_32_bits;
//
//	int i = 0;
//	for ( ; it != end; ++it, ++i )
//	{
//		unsigned char xxx = s(i, *it);
//		temp_32_bits.set(i, xxx);
//	}
//
//	std::cout << "s:  "; bit_print(temp_32_bits.elems_); std::cout << std::endl;
//
//	permutator_des<p_table>::call(temp_32_bits.elems_, final);
//	std::cout << "p:  "; bit_print(final); std::cout << std::endl;
// }
//
////// Initial permutation of blocks
////void step2()
////{
////	permute<ip_table>(block, permuted);
////	//bit_print(permuted);
////
////	////std::copy(ret_table, ret_table+56, std::ostream_iterator<char>( std::cout, "\n" ) );
////
////	//for (int i = 0; i < 8; ++i )
////	//{
////	//	std::cout << (unsigned int)permuted[i] << '\n';
////	//}
////}
////
//////Breakdown of the blocks into two parts: left and right, named L and R;
////void step3()
////{
////	left[0] = permuted[0];
////	left[1] = permuted[1];
////	left[2] = permuted[2];
////	left[3] = permuted[3];
////
////	right[0] = permuted[4];
////	right[1] = permuted[5];
////	right[2] = permuted[6];
////	right[3] = permuted[7];
////}
////
//////Permutation and substitution steps repeated 16 times (called rounds);
////void step4()
////{
////	bit_print(right);
////	std::cout << std::endl;
////	permute<expansion_table>(right, right_expanded);
////	bit_print(right_expanded);
////	std::cout << std::endl;
////
////	//-----------------------------------------------------------
////	for ( int i = 0; i < 6; ++i )
////	{
////		right_expanded_xor[i] = right_expanded[i] ^ key[i];
////	}
////
////	bit_print(right_expanded_xor);
////	std::cout << std::endl;
////
////	//-----------------------------------------------------------
////	using boost::archive::iterators::transform_width;
////
////	typedef transform_width<char*, 6, 8> base64_text;
////
////	base64_text it( right_expanded_xor );
////	base64_text end( right_expanded_xor+6 );
////	
////	for ( ; it != end; ++it )
////	{
////		//std::cout << (unsigned int)*it << std::endl;
////		std::cout << *it;
////	}
////
////
////}
////
//////Re-joining of the left and right parts then inverse initial permutation.
////void step5()
////{
////}
//
//#include <boost/mpl/for_each.hpp>
//
//struct value_printer
//{
//	template< typename U > void operator()(U x)
//	{
//		std::cout << x << ' ';
//	}
//};
//
//
//
//
//
//
//int main( /* int argc, char* argv[] */ )
//{
//	auto xxx0 = bit_adjuster::big_endian<int, 0>::value;
//	auto xxx1 = bit_adjuster::big_endian<int, 1>::value;
//	auto xxx2 = bit_adjuster::big_endian<int, 2>::value;
//	auto xxx3 = bit_adjuster::big_endian<int, 3>::value;
//	auto xxx4 = bit_adjuster::big_endian<int, 4>::value;
//	auto xxx5 = bit_adjuster::big_endian<int, 5>::value;
//	auto xxx6 = bit_adjuster::big_endian<int, 6>::value;
//	auto xxx7 = bit_adjuster::big_endian<int, 7>::value;
//	auto xxx8 = bit_adjuster::big_endian<int, 8>::value;
//
//	//step0();
//	//step1();
//	////step2();
//	////step3();
//	////step4();
//	////step5();
//
//
//	return 0;
//}
//
//
//
////---------------------------------------------------------------------------------
//
//
////template <int CharLenght, typename CharType>
////void function_xxx( CharType source, CharType & target1, CharType & target2 )
////{
////	auto bit_max = get_bit_value<CharLenght-1>(source);
////	auto bit_min = get_bit_value<0>(source);
////
////	if (bit_max != 0) 
////	{
////		set_bit_value<0>(target1, bit_max);
////	}
////	
////	if (bit_min != 0) 
////	{
////		set_bit_value<1>(target1, bit_min);
////	}
////
////	//TODO:
////}
//
////void test_column_and_row_indexes()
////{
////	//unsigned char source = 27;
////	unsigned char source = 0;
////	unsigned char target1 = 0;
////	unsigned char target2 = 0;
////
////	source = 30;	//11110
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 0);
////	assert(target2 == 15);
////
////
////	source = 27;	//011011
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 1);
////	assert(target2 == 13);
////
////
////	source = 32;	//100000
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 2);
////	assert(target2 == 0);
////
////
////	source = 33;	//100001
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 3);
////	assert(target2 == 0);
////
////
////	source = 42;	//101010
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 2);
////	assert(target2 == 5);
////
////
////	source = 21;	//010101
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 1);
////	assert(target2 == 10);
////
////
////	source = 63;	//111111
////	target1 = 0;
////	target2 = 0;
////	permutator<s_row_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 2>::call(source, target1);
////	permutator<s_column_table, bit_adjuster::little_endian_des_tables, bit_adjuster::little_endian, 6, 4>::call(source, target2);
////	assert(target1 == 3);
////	assert(target2 == 15);
////	
////
////}
//
//
////---------------------------------------------------------------------------------
//
//
//
////int main()
////{
////	using namespace std;
////
////	typedef e<18, e<23, e<42> > > arr;
////
////
////	cout << at<arr, 0>::value << endl;
////	cout << at<arr, 1>::value << endl;
////	cout << at<arr, 2>::value << endl;
////}
//
//
//
////---------------------------------------------------------------------------------
//
//
////inline int prime(int i)
////{
////	static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
////	return primes[i];
////}
////
////static const int primes_2[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
//
//
////prime(15);
////std::cout << at(primes_2, 0) << std::endl;
////std::cout << at(primes_2, 1) << std::endl;
////std::cout << at(primes_2, 2) << std::endl;
////std::cout << at(primes_2, 9) << std::endl;
////std::cout << at(primes_2, 10) << std::endl;
//
//
////---------------------------------------------------------------------------------
//
//
////static const int permutation_table[] = {
////	57, 49, 41, 33, 25, 17,  9
////	, 1, 58, 50, 42, 34, 26, 18
////	,10,  2, 59, 51, 43, 35, 27
////	,19, 11,  3, 60, 52, 44, 36
////	,63, 55, 47, 39, 31, 23, 15
////	, 7, 62, 54, 46, 38, 30, 22
////	,14,  6, 61, 53, 45, 37, 29
////	,21, 13,  5, 28, 20, 12,  4 
////};
////
////typedef e<18, e<23, e<42> > > arr;
//
//
//
////---------------------------------------------------------------------------------
//
////template <typename ArrayType, size_t Size>
////inline ArrayType at( const ArrayType (&array)[Size], size_t index )
////{
////	BOOST_ASSERT( index < Size );
////	return array[index];
////}
//
//
////template<int index>
////int bit_value_old ( int n )
////{
////	return static_cast<bool>( n & bit_mask<index>::value );
////}
//
//
//////const char xxx = permutation_table[63];
//////int mask = bit_mask<xxx>::value;
////
////int value0 = bit_value_old<0>(key[0]);
////int value1 = bit_value_old<1>(key[0]);
////int value2 = bit_value_old<2>(key[0]);
////int value3 = bit_value_old<3>(key[0]);
////int value4 = bit_value_old<4>(key[0]);
////int value5 = bit_value_old<5>(key[0]);
////int value6 = bit_value_old<6>(key[0]);
////int value7 = bit_value_old<7>(key[0]);